#include "commandLib.h"
#include "images.h"
#include "myLib.h"
#include "text.h"
#include <stdlib.h>
#include <stdio.h>

int citiesLeft = INIT_CITIES;
int cmLeft = INIT_COUNTER_MISSILES;
int emLeft = INIT_ENEMY_MISSILES;
int countdown = 3;
int score = 0;
Cursor cursor;
City city[3];
LaunchPoint lp;
Missile enemyMissiles[INIT_ENEMY_MISSILES];
Missile counterMissiles[INIT_COUNTER_MISSILES];
Explosion explosions[INIT_COUNTER_MISSILES];


void newGame()
{
	int aPressed = 1;
	cursor.r = CURSOR_INIT_R;
	cursor.c = CURSOR_INIT_C;
	lp.r = (SCREENHEIGHT-(SILO_HEIGHT))+10;
	lp.c = SILO_C+(SILO_WIDTH/2);
	city[0].r = (SCREENHEIGHT-CITYI_HEIGHT)+10;
	city[0].c = FIRST_CITY_C;
	city[1].r = (SCREENHEIGHT-CITYI_HEIGHT)+10;
	city[1].c = FIRST_CITY_C*2+CITY_BUFFER*2;
	city[2].r = (SCREENHEIGHT-CITYI_HEIGHT)+10;
	city[2].c = FIRST_CITY_C*3 + CITY_BUFFER*4;
	citiesLeft = INIT_CITIES;
	emLeft = INIT_ENEMY_MISSILES;
	cmLeft = INIT_COUNTER_MISSILES;
	for(int i = 0; i<INIT_CITIES; i++)
		city[i].status = ALIVE;
	for(int i = 0; i<INIT_ENEMY_MISSILES;i++)
	{
		enemyMissiles[i].status = UNFIRED;
		enemyMissiles[i].r = 0;
	}
	for(int i = 0; i<INIT_COUNTER_MISSILES;i++)
	{
		counterMissiles[i].status = UNFIRED;
		counterMissiles[i].r = lp.r;
		counterMissiles[i].c = lp.c;
	}
	//SHOW SPLASH
	drawImage4(0 , 0, STARTSCREEN_HEIGHT ,STARTSCREEN_WIDTH , &startScreen[0]);
	FlipPage();
	drawImage4(0 , 0, STARTSCREEN_HEIGHT ,STARTSCREEN_WIDTH , &startScreen[0]);
	FlipPage();
	int counter = 0;
	while(!(KEY_DOWN_NOW(BUTTON_START)));
	while(KEY_DOWN_NOW(BUTTON_START) && (!aPressed))
	{
		counter++;
		aPressed = KEY_DOWN_NOW(BUTTON_START);
	}
	srand(counter);
	//USE RAND TO GENERATE MISSILE TIMINGS AND POSITIONS
	for(int i = 0; i<INIT_ENEMY_MISSILES;i++)
	{
		enemyMissiles[i].c = (rand()%(SCREENWIDTH-20)) + 18;
	}
}

void checkLoseConditions()
{
	if(citiesLeft == 0)
	{
		int score = calculateScore();
		score +=0;
		while(1)
		{
			//display game over and score
			int score = calculateScore();
			char scoreChar[8];
			sprintf(scoreChar, "%d", score);
			drawImage4(0,0, GAMEOVER_HEIGHT, GAMEOVER_WIDTH, &gameover[0]);
			drawString(SCREENHEIGHT/4+4, SCREENWIDTH/2+5, scoreChar, WHITE_INDEX);
			FlipPage();
			if(KEY_DOWN_NOW(BUTTON_START))
            {
            	break;
            }
		}
		newGame();
	}
}

void checkWinConditions()
{
	int counter = 0;
    for(int i = 0; i<INIT_ENEMY_MISSILES; i++)
    {
        if(enemyMissiles[i].status == FIRED)
        	counter++;
    }
	if( (counter == INIT_ENEMY_MISSILES) && citiesLeft)
	{

		int score = calculateScore();
		score += 0;
		while(1)
		{
			//DISPLAY GAME OVER AND SCORE
			int score = calculateScore();
			char scoreChar[8];
			sprintf(scoreChar, "%d", score);
			drawImage4(0,0, GAMEOVER_HEIGHT, GAMEOVER_WIDTH, &gameover[0]);
			drawString(SCREENHEIGHT/4+4, SCREENWIDTH/2+5, scoreChar, WHITE_INDEX);
			FlipPage();
			if(KEY_DOWN_NOW(BUTTON_START))
            {
            	break;
            }
		}
		newGame();
	}
}

void fireCounterMissile()
{
	if(cmLeft >0)
	{
		u16 ci = INIT_COUNTER_MISSILES - cmLeft;
		counterMissiles[ci].r = cursor.r;
		counterMissiles[ci].c = cursor.c;
		counterMissiles[ci].status = ACTIVE;
		counterMissiles[ci].eTime = 60;
		explosions[ci].r = cursor.r -(EXPLOSIONHW/2);
		explosions[ci].c = cursor.c -(EXPLOSIONHW/2);
		cmLeft--;
	}
}

void attemptEnemyMissile()
{
	u16 chance = rand()%150;
	if(chance == 1 && emLeft)
	{	
		enemyMissiles[INIT_ENEMY_MISSILES-emLeft].status = ACTIVE;
		emLeft--;
	}
}

void updateMissiles()
{
	if(countdown == 0)
		{
		 for(int i= 0; i<INIT_ENEMY_MISSILES; i++)
		{
			if(enemyMissiles[i].status == ACTIVE)
			{
				if(enemyMissiles[i].r >=155)
				{
					enemyMissiles[i].status = FIRED;
				}
				else
					enemyMissiles[i].r++;
			}
		}
		countdown = 3;
	}
	else
		countdown--;
}

void updateCounterMissiles()
{
	for(int i = 0; i<INIT_COUNTER_MISSILES;i++)
	{
		if(counterMissiles[i].status == ACTIVE)
		{
			if(counterMissiles[i].r > counterMissiles[i].r1)
				counterMissiles[i].r--;
			if(counterMissiles[i].r < counterMissiles[i].r1)
				counterMissiles[i].r++;
			if (counterMissiles[i].c < counterMissiles[i].c1)
				counterMissiles[i].c++;
			if(counterMissiles[i].c > counterMissiles[i].c1)
				counterMissiles[i].c--;
			if(counterMissiles[i].c == counterMissiles[i].c1 && counterMissiles[i].r == counterMissiles[i].r1)
			{
				counterMissiles[i].status = EXPLODED;
				counterMissiles[i].eTime = 60;
			}
		}
		else if(counterMissiles[i].status == EXPLODED)
		{
			if(counterMissiles[i].eTime>0)
				counterMissiles[i].eTime--;
			else
				counterMissiles[i].status = FIRED;
		}
	}
}

void drawScreen()
{
	fillScreen(BACKGROUND_INDEX);
	drawGround();
	drawMissiles();
	drawCursor();
}

void drawGround()
{
	//CITY/CURSOR/SILO HERE
	drawImage4((SCREENHEIGHT-(SILO_HEIGHT)+10), SILO_C, SILO_HEIGHT, SILO_WIDTH, &silo[0]);
	for(int i = 0; i<INIT_CITIES;i++)
	{
		if(city[i].status == ALIVE)
		{
			drawImage4(city[i].r, city[i].c, CITYI_HEIGHT, CITYI_WIDTH, &cityi[0]);
		}
	}
}

// function line(x0, y0, x1, y1)
//   dx := abs(x1-x0)
//   dy := abs(y1-y0) 
//   if x0 < x1 then sx := 1 else sx := -1
//   if y0 < y1 then sy := 1 else sy := -1
//   err := dx-dy
// 
//   loop
//     setPixel(x0,y0)
//     if x0 = x1 and y0 = y1 exit loop
//     e2 := 2*err
//     if e2 > -dy then 
//       err := err - dy
//       x0 := x0 + sx
//     end if
//     if e2 <  dx then 
//       err := err + dx
//       y0 := y0 + sy 
//     end if
//   end loop

void drawLine(int r0, int r1, int c0, int c1)
{
	int sc,sr,err = 0;
	int dc = ABS(c1-c0);
	int dr = ABS(r1-r0);
	if(c0<c1)
		sc = 1;
	else
		sc = -1;
	if(r0<r1)
		sr = 1;
	else 
		sr = -1;
	err = dc-dr;
	while(r0 != r1 || c0 != c1)
	{
		setPixel4(r0, c0, CURSOR_INDEX);
		int e2 = err*2;
		if(e2 > -dr)
		{
			err -= dr;
			c0 = c0 + sc;
		}
		if(e2 < dc)
		{
			err += dc;
			r0 = r0 + sr;
		}
	}
}

void drawMissiles()
{
	//draw Enemy Missiles
	for(int i = 0; i < INIT_ENEMY_MISSILES; i++)
	{
		if(enemyMissiles[i].status == ACTIVE)
		{
			drawLine(0, enemyMissiles[i].r, enemyMissiles[i].c, enemyMissiles[i].c);
		}
	}
	//draw Counter Missiles
	for(int i = 0; i<INIT_COUNTER_MISSILES; i++)
	{
		if(counterMissiles[i].status == ACTIVE)
		{
			if(counterMissiles[i].eTime >0)
			{
				drawLine(lp.r,counterMissiles[i].r,lp.c, counterMissiles[i].c);
				drawRect4(explosions[i].r, explosions[i].c, EXPLOSIONHW, EXPLOSIONHW, silo[120]);
				//draw explosions;
				counterMissiles[i].eTime--;
			}
			else
				counterMissiles[i].status = FIRED;
		}
	}
}

void drawCursor()
{
	drawRect4(cursor.r, cursor.c, CURSORHW, CURSORHW, CURSOR_INDEX);
}

void cursorLeft()
{
	if(cursor.c>6)
	{
		//drawRect4(cursor.r, cursor.c, CURSORHW, CURSORHW, BACKGROUND_INDEX);
		cursor.c--;
	}
}

void cursorRight()
{
	if(cursor.c<234)
	{
		//drawRect4(cursor.r, cursor.c, CURSORHW, CURSORHW, BACKGROUND_INDEX);
		cursor.c++;
	}
}

void cursorUp()
{
	if(cursor.r>6)
	{
		//drawRect4(cursor.r, cursor.c, CURSORHW, CURSORHW, BACKGROUND_INDEX);
		cursor.r--;
	}
}

void cursorDown()
{
	if(cursor.r<118)
	{
		//drawRect4(cursor.r, cursor.c, CURSORHW, CURSORHW, BACKGROUND_INDEX);
		cursor.r++;
	}
}

void checkCollisions()
{
	//check for buildings to be hit
	for(int i = 0; i< INIT_ENEMY_MISSILES; i++)
	{
		if(enemyMissiles[i].status == ACTIVE)
		{
			if(enemyMissiles[i].r >= city[0].r+3)
			{
				for(int j = 0; j<INIT_CITIES; j++)
				{
					if(city[j].status == ALIVE)
					{
						if(enemyMissiles[i].c >= city[j].c && enemyMissiles[i].c <= (city[j].c + CITYI_WIDTH))
						{
							city[j].status = DEAD;
							enemyMissiles[i].status = FIRED;
							citiesLeft--;
							break;
						}
					}
				}
			}
		}
	}
	//check explosion collisions
	for ( int i = 0; i<INIT_COUNTER_MISSILES; i++)
	{
	    for(int j = 0; j<INIT_ENEMY_MISSILES; j++)
	    {
	        if(counterMissiles[i].status == ACTIVE && enemyMissiles[j].status == ACTIVE)
	        {
	            //CHECK R FIRST
	            if(explosions[i].r <= enemyMissiles[j].r && (explosions[i].r+EXPLOSIONHW) >= enemyMissiles[j].r)
	            {
	                if(explosions[i].c <= enemyMissiles[j].c && (explosions[i].c+EXPLOSIONHW) >= enemyMissiles[j].c)
	                {
	                    enemyMissiles[j].status = FIRED;
	                }
	            }
	        }
	    }
	}
}

int calculateScore()
{
	int score  = 0;
	score += citiesLeft*1000;
	score += cmLeft*50;
	score -= emLeft*50;
	return score;
}
